home *** CD-ROM | disk | FTP | other *** search
- function PROT_ListManager(opt_testing) {
- this.debugZone = "listmanager";
- if (opt_testing)
- this.debugZone += "testing";
- G_debugService.enableZone(this.debugZone);
- this.testing_ = !!opt_testing;
- this.currentUpdateChecker_ = null; // set when we toggle updates
- this.rpcPending_ = false;
- var self = this;
- this.updateserverURL_ = PROT_globalStore.getUpdateserverURL();
- this.tablesKnown_ = {};
- if (this.testing_) {
- this.tablesKnown_ = {
- "test1-foo-domain": new PROT_VersionParser("test1-foo-domain", 0, -1),
- "test2-foo-domain": new PROT_VersionParser("test2-foo-domain", 0, -1),
- "test-white-domain": new PROT_VersionParser("test-white-domain", 0, -1,
- true /* require mac*/),
- "test-mac-domain": new PROT_VersionParser("test-mac-domain", 0, -1,
- true /* require mac */)
- };
- }
- this.tablesData_ = {};
- this.registrar_ = new EventRegistrar({});
- this.urlCrypto_ = null;
- this.prefs_ = new G_Preferences();
- }
- PROT_ListManager.prototype.registerTable = function(tableName,
- opt_requireMac,
- opt_callback) {
- var table = new PROT_VersionParser(tableName, 1, -1, opt_requireMac);
- this.tablesKnown_[tableName] = table;
- this.tablesData_[tableName] = new PROT_TRTable(tableName);
- if (opt_callback) {
- if (!this.registrar_.isKnownEventType(tableName))
- this.registrar_.addEventType(tableName);
- this.registrar_.registerListener(tableName, opt_callback);
- G_Debug(this, "registering callback for " + tableName);
- }
- return true;
- }
- PROT_ListManager.prototype.enableUpdateTables = function(tables) {
- var changed = false;
- for (var i = 0; i < tables.length; ++i) {
- var table = this.tablesKnown_[tables[i]];
- if (table) {
- G_Debug(this, "Enabling table updates for " + tables[i]);
- table.needsUpdate = true;
- changed = true;
- }
- }
- if (changed === true)
- this.maybeToggleUpdateChecking();
- }
- PROT_ListManager.prototype.disableUpdateTables = function(tables) {
- var changed = false;
- for (var i = 0; i < tables.length; ++i) {
- var table = this.tablesKnown_[tables[i]];
- if (table) {
- G_Debug(this, "Disabling table updates for " + tables[i]);
- table.needsUpdate = false;
- changed = true;
- }
- }
- if (changed === true)
- this.maybeToggleUpdateChecking();
- }
- PROT_ListManager.prototype.requireTableUpdates = function() {
- for (var type in this.tablesKnown_) {
- if (this.tablesKnown_[type].major == 0)
- continue;
- if (this.tablesKnown_[type].needsUpdate)
- return true;
- }
- return false;
- }
- PROT_ListManager.prototype.maybeStartManagingUpdates = function() {
- if (this.testing_)
- return;
- this.maybeToggleUpdateChecking();
- }
- PROT_ListManager.prototype.maybeToggleUpdateChecking = function() {
- if (this.testing_)
- return;
- if (this.requireTableUpdates() === true) {
- G_Debug(this, "Starting managing lists");
- this.loadTableVersions_();
- if (!this.currentUpdateChecker_)
- this.currentUpdateChecker_ =
- new G_Alarm(BindToObject(this.checkForUpdates, this), 3000);
- this.startUpdateChecker();
- } else {
- G_Debug(this, "Stopping managing lists (if currently active)");
- this.stopUpdateChecker(); // Cancel pending updates
- }
- }
- PROT_ListManager.prototype.startUpdateChecker = function() {
- this.stopUpdateChecker();
- var thirtyMinutes = 30 * 60 * 1000;
- this.updateChecker_ = new G_Alarm(BindToObject(this.checkForUpdates, this),
- thirtyMinutes, true /* repeat */);
- }
- PROT_ListManager.prototype.stopUpdateChecker = function() {
- if (this.updateChecker_) {
- this.updateChecker_.cancel();
- this.updateChecker_ = null;
- }
- }
- PROT_ListManager.prototype.safeLookup = function(table, key) {
- var result = false;
- try {
- var map = this.tablesData_[table];
- result = map.find(key);
- } catch(e) {
- result = false;
- G_Debug(this, "Safelookup masked failure for " + table + ", key " + key + ": " + e);
- }
- return result;
- }
- PROT_ListManager.prototype.safeInsert = function(table, key, value) {
- if (!this.tablesKnown_[table]) {
- G_Debug(this, "Unknown table: " + table);
- return false;
- }
- if (!this.tablesData_[table])
- this.tablesData_[table] = new PROT_TRTable(table);
- try {
- this.tablesData_[table].insert(key, value);
- } catch (e) {
- G_Debug(this, "Cannot insert key " + key + " value " + value);
- G_Debug(this, e);
- return false;
- }
- return true;
- }
- PROT_ListManager.prototype.safeErase = function(table, key) {
- if (!this.tablesKnown_[table]) {
- G_Debug(this, "Unknown table: " + table);
- return false;
- }
- if (!this.tablesData_[table])
- return false;
- return this.tablesData_[table].erase(key);
- }
- PROT_ListManager.prototype.loadTableVersions_ = function() {
- var prefBase = PROT_globalStore.getTableVersionPrefPrefix();
- for (var table in this.tablesKnown_) {
- var version = this.prefs_.getPref(prefBase + table, "1.-1");
- G_Debug(this, "loadTableVersion " + table + ": " + version);
- var tokens = version.split(".");
- G_Assert(this, tokens.length == 2, "invalid version number");
- this.tablesKnown_[table].major = tokens[0];
- this.tablesKnown_[table].minor = tokens[1];
- }
- }
- PROT_ListManager.prototype.setTableVersions_ = function(updateString) {
- var updatedTables = [];
- var prefBase = PROT_globalStore.getTableVersionPrefPrefix();
- var startPos = updateString.indexOf('[');
- var endPos;
- while (startPos != -1) {
- if (0 == startPos || ('\n' == updateString[startPos - 1] &&
- '\n' == updateString[startPos - 2])) {
- endPos = updateString.indexOf('\n', startPos);
- if (endPos != -1) {
- var line = updateString.substring(startPos, endPos);
- var versionParser = new PROT_VersionParser("dummy");
- if (versionParser.fromString(line)) {
- var tableName = versionParser.type;
- var version = versionParser.major + '.' + versionParser.minor;
- G_Debug(this, "Set table version for " + tableName + ": " + version);
- this.prefs_.setPref(prefBase + tableName, version);
- this.tablesKnown_[tableName].ImportVersion(versionParser);
- updatedTables.push(tableName);
- }
- }
- }
- startPos = updateString.indexOf('[', startPos + 1);
- }
- return updatedTables;
- }
- PROT_ListManager.prototype.getRequestURL_ = function(url) {
- url += "version=";
- var firstElement = true;
- var requestMac = false;
- for (var type in this.tablesKnown_) {
- if (this.tablesKnown_[type].major == 0)
- continue;
- if (this.tablesKnown_[type].needsUpdate == false)
- continue;
- if (!firstElement) {
- url += ","
- } else {
- firstElement = false;
- }
- url += type + ":" + this.tablesKnown_[type].toUrl();
- if (this.tablesKnown_[type].requireMac)
- requestMac = true;
- }
- if (requestMac) {
- if (!this.urlCrypto_)
- this.urlCrypto_ = new PROT_UrlCrypto();
- url += "&wrkey=" +
- encodeURIComponent(this.urlCrypto_.getManager().getWrappedKey());
- }
- G_Debug(this, "getRequestURL returning: " + url);
- return url;
- }
- PROT_ListManager.prototype.checkForUpdates = function() {
- this.currentUpdateChecker_ = null;
- if (this.rpcPending_) {
- G_Debug(this, 'checkForUpdates: old callback is still pending...');
- return false;
- }
- G_Debug(this, 'checkForUpdates: scheduling request..');
- this.rpcPending_ = true;
- this.xmlFetcher_ = new PROT_XMLFetcher();
- this.xmlFetcher_.get(this.getRequestURL_(this.updateserverURL_),
- BindToObject(this.rpcDone, this));
- return true;
- }
- PROT_ListManager.prototype.rpcDone = function(data) {
- G_Debug(this, "Called rpcDone");
- this.rpcPending_ = false;
- this.xmlFetcher_ = null;
- if (!data || !data.length) {
- G_Debug(this, "No data. Returning");
- return;
- }
- data = this.checkMac_(data);
- if (data.length == 0) {
- return;
- }
- var dbUpdateSrv = Cc["@google.com/dbupdateservice;1"]
- .getService(Ci.GTBIDbUpdateService);
- try {
- dbUpdateSrv.updateTables(data);
- } catch (e) {
- G_Debug(this, "Skipping update, write thread busy.");
- return;
- }
- var tableNames = this.setTableVersions_(data);
- G_Debug(this, "Updated tables: " + tableNames);
- for (var t = 0, name = null; name = tableNames[t]; ++t) {
- if (!this.tablesData_[name])
- this.tablesData_[name] = new PROT_TRTable(name);
- if (this.registrar_.isKnownEventType(name)) {
- this.registrar_.fire(name, { table: this.tablesData_[name] });
- }
- }
- }
- PROT_ListManager.prototype.checkMac_ = function(data) {
- var dataTables = data.split('\n\n');
- var returnString = "";
- for (var t = 0; t < dataTables.length; ++t) {
- var table = dataTables[t];
- var firstLineEnd = table.indexOf("\n");
- while (firstLineEnd == 0) {
- table = table.substring(1);
- firstLineEnd = table.indexOf("\n");
- }
- if (firstLineEnd == -1) {
- G_Debug(this, "expecting at least 2 lines");
- continue;
- }
- var versionLine = table.substring(0, firstLineEnd);
- var versionParser = new PROT_VersionParser("dummy");
- if (!versionParser.fromString(versionLine)) {
- G_Debug(this, "Failed to parse version string");
- continue;
- }
- if (versionParser.mac && versionParser.macval.length > 0) {
- var updateData = table.substring(firstLineEnd + 1) + '\n';
- if (!this.urlCrypto_)
- this.urlCrypto_ = new PROT_UrlCrypto();
- var computedMac = this.urlCrypto_.computeMac(updateData);
- if (computedMac != versionParser.macval) {
- G_Debug(this, "mac doesn't match: " + computedMac + " != " +
- versionParser.macval)
- continue;
- }
- } else {
- if (this.tablesKnown_[versionParser.type] &&
- this.tablesKnown_[versionParser.type].requireMac) {
- G_Debug(this, "mac required but none provided");
- continue;
- }
- }
- returnString += table + "\n\n";
- }
- return returnString;
- }
- function TEST_PROT_ListManager() {
- if (G_GDEBUG) {
- var z = "listmanager UNITTEST";
- G_debugService.enableZone(z);
- G_Debug(z, "Starting");
- var listManager = new PROT_ListManager(true /*testing*/);
- var data = "a bad update string";
- G_Assert(z, "" == listManager.checkMac_(data),
- "checkMac returned bogus string");
- data = "[test-foo-domain 1.12]\n+http://foo.com\n\n";
- G_Assert(z, data == listManager.checkMac_("\n\n" + data),
- "failed to parse extra new lines");
- data = "[test-foo-domain 1.12]\n+http://foo.com\n\n";
- G_Assert(z, data == listManager.checkMac_("\n\n" + data),
- "extra newlines");
- data = "[test-foo-domain 1.12]\n+http://foo.com" +
- "\n\n" +
- "[test-bar-domain 1.23]\n+http://bar.com\n\n";
- G_Assert(z, data == listManager.checkMac_(data),
- "failed to parse 1 blank line between tables");
- var dataExtra = "[test-foo-domain 1.12]\n+http://foo.com" +
- "\n\n\n" +
- "[test-bar-domain 1.23]\n+http://bar.com\n\n";
- G_Assert(z, data == listManager.checkMac_(dataExtra),
- "failed to parse 2 blank line between tables");
- var dataExtra = "[test-foo-domain 1.12]\n+http://foo.com" +
- "\n\n\n\n" +
- "[test-bar-domain 1.23]\n+http://bar.com\n\n";
- G_Assert(z, data == listManager.checkMac_(dataExtra),
- "failed to parse 3 blank line between tables");
- data = "[test4-badheader-url 1.asfd dfui]\n+http://www.google.com/\n";
- G_Assert(z, "" == listManager.checkMac_(data),
- "invalid header allowed");
- data = "[test4-bad-name-url 1.asfd dfui]\n+http://www.google.com/\n";
- G_Assert(z, "" == listManager.checkMac_(data),
- "invalid header allowed");
- data = "";
- var set1Name = "test1-foo-domain";
- data += "[" + set1Name + " 1.2]\n";
- var set1 = {};
- for (var i = 0; i < 10; i++) {
- set1["http://" + i + ".com"] = 1;
- data += "+" + i + ".com\t1\n";
- }
- data += "\n";
- var set2Name = "test2-foo-domain";
- data += "\n[" + set2Name + " 1.7]\n";
- var set2 = {};
- for (var i = 0; i < 5; i++) {
- set2["http://" + i + ".com"] = 1;
- data += "+" + i + ".com\t1\n";
- }
- data += "\n";
- var set3Name = "test-white-domain";
- var set3data = "";
- var set3 = {};
- for (var i = 1; i <= 3; i++) {
- set3["http://white" + i + ".com"] = 1;
- set3data += "+white" + i + ".com\t1\n";
- }
- if (!listManager.urlCrypto_)
- listManager.urlCrypto_ = new PROT_UrlCrypto();
- var macval = listManager.urlCrypto_.computeMac(set3data);
- data += "\n[" + set3Name + " 1.1][mac=" + macval + "]\n";
- data += set3data;
- var newval = "012" + macval.substr(3);
- var set4Name = "test-mac-domain";
- data += "\n";
- data += "\n[" + set4Name + " 1.1][mac=" + newval + "]\n";
- data += set3data;
- data += "\n" +
- "[test4-badheader-url 1.asfd dfui]\n" + // Malformed header
- "+foo1\tbar\n" +
- "+foo2\tbar\n" +
- "+foo3\tbar\n" +
- "+foo4\tbar\n";
- "\n" +
- "[test4-bad-name-url 1.asfd dfui]\n" + // Malformed header
- "+foo1\tbar\n" +
- "+foo2\tbar\n" +
- "+foo3\tbar\n" +
- "+foo4\tbar\n";
- function checkTables() {
- var prefBase = PROT_globalStore.getTableVersionPrefPrefix();
- var vp;
- for (var prop in set1) {
- G_Assert(z,
- listManager.tablesData_[set1Name].find(prop) == 1,
- "Couldn't find member " + prop + " of set1");
- listManager.tablesData_[set1Name].erase(prop);
- vp = listManager.tablesKnown_[set1Name];
- }
- G_Assert(z, "2" == vp.minor, "set1 table version mismatch");
- G_Assert(z, "1.2" == listManager.prefs_.getPref(prefBase + vp.type),
- "set1 table version mismatch (pref)");
- for (var prop in set2) {
- G_Assert(z,
- listManager.tablesData_[set2Name].find(prop) == 1,
- "Couldn't find member " + prop + " of set2");
- listManager.tablesData_[set2Name].erase(prop);
- }
- vp = listManager.tablesKnown_[set2Name];
- G_Assert(z, "7" == vp.minor, "set2 table version mismatch");
- G_Assert(z, "1.7" == listManager.prefs_.getPref(prefBase + vp.type),
- "set2 table version mismatch (pref)");
- for (var prop in set3) {
- G_Assert(z,
- listManager.tablesData_[set3Name].find(prop) == 1,
- "Couldn't find member " + prop + " of set3 from disk.");
- listManager.tablesData_[set3Name].erase(prop);
- }
- vp = listManager.tablesKnown_[set3Name];
- G_Assert(z, "1" == vp.minor, "set3 table version mismatch " + vp.minor);
- G_Assert(z, "1.1" == listManager.prefs_.getPref(prefBase + vp.type),
- "set3 table version mismatch (pref)");
- G_Assert(z,
- !listManager.tablesData_[set4Name],
- "Set 4 shouldn't exist! It had the wrong mac.");
- G_Debug(z, "PASSED");
- z = "dbupdateservice UNITTEST";
- G_Debug(z, "Starting");
- var data =
- "[test1-black-url 1.1]\n" +
- "+foo1\tbar\n" +
- "+foo2\n" + // Malformed
- "+foo3\tbar\n" +
- "+foo4\tbar\n" +
- "\n" +
- "[test2-black-url 1.2]\n" +
- "+foo1\tbar\n" +
- "+foo2\tbar\n" +
- "+foo3\tbar\n" +
- "+foo4\tbar\n" +
- "\n" +
- "[test3-black-url 1.3]\n" +
- "+foo1\tbar\n" +
- "+foo2\tbar\n" +
- "+foo3\tbar\n" +
- "+foo4\n" + // Malformed
- "\n" +
- "[test4-black-url 1.4]\n" +
- "+foo1\tbar\n" +
- "+foo2\tbar\n" +
- "+foo3\tbar\n" +
- "+foo4\tbar\n" +
- "\n";
- var dbUpdateSrv = Cc["@google.com/dbupdateservice;1"]
- .getService(Ci.GTBIDbUpdateService);
- dbUpdateSrv.updateTables(data);
- function dbupdateCheckTables2() {
- G_Debug(z, "Starting checks after callback 2");
- var table = new PROT_TRTable("test4-black-url");
- G_Assert(z, table.dbTable_.exists("foo2") == "bar", "missing key foo2");
- G_Assert(z, table.dbTable_.exists("foo4") == "bar", "missing key foo4");
- G_Assert(z, table.dbTable_.exists("foo5") == "bar", "missing key foo5");
- G_Assert(z, !table.dbTable_.exists("foo1"), "foo1 not removed");
- G_Assert(z, !table.dbTable_.exists("foo3"), "foo2 not removed");
- table.dbTable_.remove("foo2");
- table.dbTable_.remove("foo4");
- table.dbTable_.remove("foo5");
- G_Debug(z, "PASSED");
- }
- function dbupdateCheckTables1() {
- G_Debug(z, "Starting checks after callback 1");
- var table = new PROT_TRTable("test1-black-url");
- var i;
- G_Assert(z, !table.dbTable_.exists("foo2"),
- "test1: found malformed key/value pair");
- for (i = 1; i <= 4; ++i)
- table.erase("foo" + i);
- table = new PROT_TRTable("test2-black-url");
- for (i = 1; i <= 4; ++i) {
- G_Assert(z, table.dbTable_.exists("foo" + i) == "bar",
- "test2: missing key foo" + i);
- table.erase("foo" + i);
- }
- table = new PROT_TRTable("test3-black-url");
- G_Assert(z, !table.dbTable_.exists("foo4"),
- "test3: found malformed key/value pair");
- for (i = 1; i <= 4; ++i)
- table.erase("foo" + i);
- table = new PROT_TRTable("test4-black-url");
- for (i = 1; i <= 4; ++i) {
- G_Assert(z, table.dbTable_.exists("foo" + i) == "bar",
- "test4: missing key foo" + i);
- }
- G_Debug(z, "First set of tests passed, moving on to second set");
- var data =
- "[test4-black-url 1.5]\n" +
- "-foo1\n" +
- "+foo5\tbar\n" +
- "-foo3\n" +
- "\n";
- dbUpdateSrv.updateTables(data);
- new G_Alarm(dbupdateCheckTables2, 800);
- }
- new G_Alarm(dbupdateCheckTables1, 800);
- }
- }
- }
-